home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / MPW / indent 1.8 / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-19  |  20.6 KB  |  919 lines  |  [TEXT/MPS ]

  1. /* Copyright (c) 1992, Free Software Foundation, Inc.  All rights reserved.
  2.  
  3.    Copyright (c) 1985 Sun Microsystems, Inc. Copyright (c) 1980 The Regents
  4.    of the University of California. Copyright (c) 1976 Board of Trustees of
  5.    the University of Illinois. All rights reserved.
  6.  
  7.    Redistribution and use in source and binary forms are permitted
  8.    provided that
  9.    the above copyright notice and this paragraph are duplicated in all such
  10.    forms and that any documentation, advertising materials, and other
  11.    materials related to such distribution and use acknowledge that the
  12.    software was developed by the University of California, Berkeley, the
  13.    University of Illinois, Urbana, and Sun Microsystems, Inc.  The name of
  14.    either University or Sun Microsystems may not be used to endorse or
  15.    promote products derived from this software without specific prior written
  16.    permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
  18.    OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
  19.  
  20.  
  21. #include "sys.h"
  22. #include "indent.h"
  23. #include <ctype.h>
  24.  
  25. #ifdef VMS
  26. #   include <file.h>
  27. #   include <types.h>
  28. #   include <stat.h>
  29. #else  /* not VMS */
  30.  
  31. /* POSIX says that <fcntl.h> should exist.  Some systems might need to use
  32.    <sys/fcntl.h> or <sys/file.h> instead.  */
  33. #include <fcntl.h>
  34.  
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37. #endif /* not VMS */
  38.  
  39. /* number of levels a label is placed to left of code */
  40. #define LABEL_OFFSET 2
  41.  
  42.  
  43. /* Stuff that needs to be shared with the rest of indent. Documented in
  44.    indent.h.  */
  45. char *in_prog;
  46. char *in_prog_pos;
  47. char *cur_line;
  48. unsigned long in_prog_size;
  49. FILE *output;
  50. char *buf_ptr;
  51. char *buf_end;
  52. int had_eof;
  53. int out_lines;
  54. int com_lines;
  55.  
  56. int suppress_blanklines = 0;
  57. static int comment_open;
  58.  
  59. int paren_target;
  60.  
  61. /* Use `perror' to print the system error message
  62.    caused by OFFENDER. */
  63.  
  64. static char *errbuf;
  65.  
  66. void
  67. sys_error (offender)
  68.      char *offender;
  69. {
  70.   int size = strlen (offender);
  71.   static int buffer_size;
  72.  
  73.   if (errbuf == 0)
  74.     {
  75.       buffer_size = size + 10;    /* Extra for random unix lossage */
  76.       errbuf = (char *) xmalloc (buffer_size);
  77.     }
  78.   else if (size + 10 > buffer_size)
  79.     {
  80.       buffer_size = size + 10;
  81.       errbuf = xrealloc (errbuf, buffer_size);
  82.     }
  83.   sprintf (errbuf, "indent: %s", offender);
  84.   perror (errbuf);
  85.   exit (1);
  86. }
  87.  
  88. #ifdef VMS
  89. int
  90. vms_read (int file_desc, void *buffer, int nbytes)
  91. {
  92.     register char *bufp;
  93.     register int nread, nleft;
  94.  
  95.     bufp  = buffer;
  96.     nread = 0;
  97.     nleft = nbytes;
  98.  
  99.     while (nread = read (file_desc, bufp, nleft), nread > 0)
  100.       {
  101.         bufp += nread;
  102.         nleft -= nread;
  103.         if (nleft < 0)
  104.             sys_error ("Internal buffering error");
  105.     }
  106.  
  107.     return nread;
  108. }
  109. #endif /* VMS */
  110.  
  111. INLINE int
  112. count_columns (column, bp)
  113.      int column;
  114.      char *bp;
  115. {
  116.   while (*bp != '\0')
  117.     {
  118.       switch (*bp++)
  119.     {
  120.     case EOL:
  121.     case 014:        /* form feed */
  122.       column = 1;
  123.       break;
  124.     case TAB:
  125.       column += tabsize - (column - 1) % tabsize;
  126.       break;
  127.     case 010:        /* backspace */
  128.       --column;
  129.       break;
  130.     default:
  131.       ++column;
  132.       break;
  133.     }
  134.     }
  135.  
  136.   return column;
  137. }
  138.  
  139. /* Return the column we are at in the input line. */
  140.  
  141. INLINE int
  142. current_column ()
  143. {
  144.   char *p;
  145.   int column = 1;
  146.  
  147.   if (buf_ptr >= save_com.ptr && buf_ptr <= save_com.end)
  148.     p = save_com.ptr;
  149.   else
  150.     p = cur_line;
  151.  
  152. #if 0
  153.   /* Paranoia */
  154.   if (! (buf_ptr >= cur_line && buf_ptr < in_prog_pos))
  155.     abort ();
  156. #endif
  157.  
  158.   column = 1;
  159.   while (p < buf_ptr)
  160.     switch (*p++)
  161.       {
  162.       case EOL:
  163.       case 014:            /* form feed */
  164.     column = 1;
  165.     break;
  166.       case TAB:
  167.     column += tabsize - (column - 1) % tabsize;
  168. #if 0
  169.     column += tabsize - (column % tabsize) + 1;
  170. #endif
  171.     break;
  172.       case '\b':        /* backspace */
  173.     column--;
  174.     break;
  175.       default:
  176.     column++;
  177.     break;
  178.       }
  179.  
  180.   return column;
  181. }
  182.  
  183. void
  184. dump_line ()
  185. {                /* dump_line is the routine that actually
  186.                    effects the printing of the new source. It
  187.                    prints the label section, followed by the
  188.                    code section with the appropriate nesting
  189.                    level, followed by any comments */
  190.   register int cur_col;
  191.   register int target_col = 0;
  192.   static not_first_line;
  193.  
  194.   if (parser_state_tos->procname[0])
  195.     {
  196.       if (troff)
  197.     {
  198.       if (comment_open)
  199.         {
  200.           comment_open = 0;
  201.           fprintf (output, ".*/\n");
  202.         }
  203.       fprintf (output, ".Pr \"%.*s\"\n",
  204.            parser_state_tos->procname_end - parser_state_tos->procname,
  205.            parser_state_tos->procname);
  206.     }
  207.       parser_state_tos->ind_level = 0;
  208.       parser_state_tos->procname = "\0";
  209.     }
  210.  
  211.   /* A blank line */
  212.   if (s_code == e_code && s_lab == e_lab && s_com == e_com)
  213.     {
  214.       /* If we have a formfeed on a blank line, we should just output it,
  215.          rather than treat it as a normal blank line.  */
  216.       if (parser_state_tos->use_ff)
  217.     {
  218.       putc ('\014', output);
  219.       parser_state_tos->use_ff = false;
  220.     }
  221.       else
  222.     {
  223.       if (suppress_blanklines > 0)
  224.         suppress_blanklines--;
  225.       else
  226.         {
  227.           parser_state_tos->bl_line = true;
  228.           n_real_blanklines++;
  229.         }
  230.     }
  231.     }
  232.   else
  233.     {
  234.       suppress_blanklines = 0;
  235.       parser_state_tos->bl_line = false;
  236.       if (prefix_blankline_requested
  237.       && not_first_line
  238.       && n_real_blanklines == 0)
  239.     n_real_blanklines = 1;
  240.       else if (swallow_optional_blanklines && n_real_blanklines > 1)
  241.     n_real_blanklines = 1;
  242.  
  243.       while (--n_real_blanklines >= 0)
  244.     putc (EOL, output);
  245.       n_real_blanklines = 0;
  246.       if (parser_state_tos->ind_level == 0)
  247.     parser_state_tos->ind_stmt = 0;    /* this is a class A kludge. dont do
  248.                        additional statement indentation
  249.                        if we are at bracket level 0 */
  250.  
  251.       if (e_lab != s_lab || e_code != s_code)
  252.     ++code_lines;        /* keep count of lines with code */
  253.  
  254.  
  255.       if (e_lab != s_lab)
  256.     {            /* print lab, if any */
  257.       if (comment_open)
  258.         {
  259.           comment_open = 0;
  260.           fprintf (output, ".*/\n");
  261.         }
  262.       while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == TAB))
  263.         e_lab--;
  264.       cur_col = pad_output (1, compute_label_target ());
  265.       if (s_lab[0] == '#' && (strncmp (s_lab, "#else", 5) == 0
  266.                   || strncmp (s_lab, "#endif", 6) == 0))
  267.         {
  268.           /* Treat #else and #endif as a special case because any text
  269.              after #else or #endif should be converted to a comment.  */
  270.           register char *s = s_lab;
  271.           if (e_lab[-1] == EOL)
  272.         e_lab--;
  273.           do
  274.         putc (*s++, output);
  275.           while (s < e_lab && 'a' <= *s && *s <= 'z');
  276.           while ((*s == ' ' || *s == TAB) && s < e_lab)
  277.         s++;
  278.           if (s < e_lab)
  279.         {
  280.           if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
  281.             fprintf (output, (tabsize > 1 ? "\t%.*s" : "  %.*s"),
  282.                  e_lab - s, s);
  283.           else
  284.             fprintf (output, (tabsize > 1
  285.                       ? "\t/* %.*s */"
  286.                       : "  /* %.*s */"),
  287.                  e_lab - s, s);
  288.         }
  289.         }
  290.       else
  291.         fprintf (output, "%.*s", e_lab - s_lab, s_lab);
  292.       cur_col = count_columns (cur_col, s_lab);
  293.     }
  294.       else
  295.     cur_col = 1;        /* there is no label section */
  296.  
  297.       parser_state_tos->pcase = false;
  298.  
  299.       if (s_code != e_code)
  300.     {            /* print code section, if any */
  301.       register char *p;
  302.       register i;
  303.  
  304.       if (comment_open)
  305.         {
  306.           comment_open = 0;
  307.           fprintf (output, ".*/\n");
  308.         }
  309.  
  310.       /* If a comment begins this line, then indent it to the right
  311.          column for comments, otherwise the line starts with code,
  312.          so indent it for code. */
  313.       if (embedded_comment_on_line == 1)
  314.         target_col = parser_state_tos->com_col;
  315.       else
  316.         target_col = compute_code_target ();
  317.  
  318.       /* If a line ends in an lparen character, the following line should
  319.          not line up with the parenthesis, but should be indented by the
  320.          usual amount.  */
  321.       if (parser_state_tos->last_token == lparen)
  322.         {
  323.           parser_state_tos->paren_indents[parser_state_tos->p_l_follow - 1]
  324.         += ind_size - 1;
  325.         }
  326.  
  327.       for (i = 0; i < parser_state_tos->p_l_follow; i++)
  328.         if (parser_state_tos->paren_indents[i] >= 0)
  329.           parser_state_tos->paren_indents[i]
  330.         = -(parser_state_tos->paren_indents[i] + target_col);
  331.  
  332.       cur_col = pad_output (cur_col, target_col);
  333.       for (p = s_code; p < e_code; p++)
  334.         {
  335. #if 0
  336.           if (*p == (char) 0200)
  337.         fprintf (output, "%d", (int) (target_col * 7));
  338.           else
  339.         if (tabsize > 1)
  340. #endif
  341.         putc (*p, output);
  342.  
  343. #if 0
  344.           else
  345.         {
  346.           int width = 1;
  347.           if (*p == TAB)
  348.             width = (tabsize - ((cur_col - 1) % tabsize));
  349.           cur_col += width;
  350.           while (width--)
  351.             putc (*p, output);
  352.         }
  353. #endif
  354.         }
  355.       cur_col = count_columns (cur_col, s_code);
  356.     }
  357.  
  358.       if (s_com != e_com)
  359.     {
  360.       if (troff)
  361.         {
  362.           int all_here = 0;
  363.           register char *p;
  364.  
  365.           if (e_com[-1] == '/' && e_com[-2] == '*')
  366.         e_com -= 2, all_here++;
  367.           while (e_com > s_com && e_com[-1] == ' ')
  368.         e_com--;
  369.           *e_com = 0;
  370.           p = s_com;
  371.           while (*p == ' ')
  372.         p++;
  373.           if (p[0] == '/' && p[1] == '*')
  374.         p += 2, all_here++;
  375.           else if (p[0] == '*')
  376.         p += p[1] == '/' ? 2 : 1;
  377.           while (*p == ' ')
  378.         p++;
  379.           if (*p == 0)
  380.         goto inhibit_newline;
  381.           if (comment_open < 2 && parser_state_tos->box_com)
  382.         {
  383.           comment_open = 0;
  384.           fprintf (output, ".*/\n");
  385.         }
  386.           if (comment_open == 0)
  387.         {
  388.           if ('a' <= *p && *p <= 'z')
  389.             *p = *p + 'A' - 'a';
  390.           if (e_com - p < 50 && all_here == 2)
  391.             {
  392.               register char *follow = p;
  393.               fprintf (output, "\n.nr C! \\w\1");
  394.               while (follow < e_com)
  395.             {
  396.               switch (*follow)
  397.                 {
  398.                 case EOL:
  399.                   putc (' ', output);
  400.                 case 1:
  401.                   break;
  402.                 case '\\':
  403.                   putc ('\\', output);
  404.                 default:
  405.                   putc (*follow, output);
  406.                 }
  407.               follow++;
  408.             }
  409.               putc (1, output);
  410.             }
  411.           fprintf (output, "\n./* %dp %d %dp\n",
  412.                (int) (parser_state_tos->com_col * 7),
  413.                (int) ((s_code != e_code || s_lab != e_lab)
  414.                   - parser_state_tos->box_com),
  415.                (int) (target_col * 7));
  416.         }
  417.           comment_open = 1 + parser_state_tos->box_com;
  418.           while (*p)
  419.         {
  420.           if (*p == BACKSLASH)
  421.             putc (BACKSLASH, output);
  422.           putc (*p++, output);
  423.         }
  424.         }
  425.       else
  426.         {
  427.           /* Here for comment printing.  This code is new as of
  428.              version 1.8 */
  429.           register target = parser_state_tos->com_col;
  430.           register char *com_st = s_com;
  431.  
  432.           if (cur_col > target)
  433.         {
  434.           putc (EOL, output);
  435.           cur_col = 1;
  436.           ++out_lines;
  437.         }
  438.  
  439.           cur_col = pad_output (cur_col, target);
  440.           fwrite (com_st, e_com - com_st, 1, output);
  441.           cur_col += e_com - com_st;
  442.           com_lines++;
  443.         }
  444.     }
  445.       else if (embedded_comment_on_line)
  446.     com_lines++;
  447.       embedded_comment_on_line = 0;
  448.  
  449.       if (parser_state_tos->use_ff)
  450.     {
  451.       putc ('\014', output);
  452.       parser_state_tos->use_ff = false;
  453.     }
  454.       else
  455.     putc (EOL, output);
  456.  
  457.     inhibit_newline:
  458.       ++out_lines;
  459.       if (parser_state_tos->just_saw_decl == 1
  460.       && blanklines_after_declarations)
  461.     {
  462.       prefix_blankline_requested = 1;
  463.       parser_state_tos->just_saw_decl = 0;
  464.     }
  465.       else
  466.     prefix_blankline_requested = postfix_blankline_requested;
  467.       postfix_blankline_requested = 0;
  468.     }
  469.  
  470.   /* if we are in the middle of a declaration, remember that fact
  471.      for proper comment indentation */
  472.   parser_state_tos->decl_on_line = parser_state_tos->in_decl;
  473.  
  474.   /* next line should be indented if we have not completed this
  475.      stmt and if we are not in the middle of a declaration */
  476.   parser_state_tos->ind_stmt = (parser_state_tos->in_stmt
  477.                 & ~parser_state_tos->in_decl);
  478.  
  479.   parser_state_tos->dumped_decl_indent = 0;
  480.   *(e_lab  = s_lab) = '\0';    /* reset buffers */
  481.   *(e_code = s_code) = '\0';
  482.   *(e_com  = s_com) = '\0';
  483.   parser_state_tos->ind_level = parser_state_tos->i_l_follow;
  484.   parser_state_tos->paren_level = parser_state_tos->p_l_follow;
  485.   if (parser_state_tos->paren_level > 0)
  486.     paren_target
  487.       = -parser_state_tos->paren_indents[parser_state_tos->paren_level - 1];
  488.   else
  489.     paren_target = 0;
  490.   not_first_line = 1;
  491.  
  492.   return;
  493. }
  494.  
  495. /* Return the column in which we should place the code about to be output. */
  496.  
  497. INLINE int
  498. compute_code_target ()
  499. {
  500.   register target_col = parser_state_tos->ind_level + 1;
  501.   register w, t;
  502.  
  503.   if (! parser_state_tos->paren_level)
  504.     {
  505.       if (parser_state_tos->ind_stmt)
  506.     target_col += continuation_indent;
  507.       return target_col;
  508.     }
  509.  
  510.   if (!lineup_to_parens)
  511.     return target_col + (continuation_indent * parser_state_tos->paren_level);
  512.  
  513.   t = paren_target;
  514.   if ((w = count_columns (t, s_code) - max_col) > 0
  515.       && count_columns (target_col, s_code) <= max_col)
  516.     {
  517.       t -= w + 1;
  518.       if (t > target_col)
  519.     target_col = t;
  520.     }
  521.   else
  522.     target_col = t;
  523.  
  524.   return target_col;
  525. }
  526.  
  527. INLINE int
  528. compute_label_target ()
  529. {
  530.   return
  531.   parser_state_tos->pcase ? case_ind + 1
  532.   : *s_lab == '#' ? 1
  533.   : parser_state_tos->ind_level - LABEL_OFFSET + 1;
  534. }
  535.  
  536. /* VMS defines it's own read routine, `vms_read' */
  537. #ifndef SYS_READ
  538. #define SYS_READ read
  539. #endif
  540.  
  541. /* Read file FILENAME into a `fileptr' structure, and return a pointer to
  542.    that structure. */
  543.  
  544. static struct file_buffer fileptr;
  545.  
  546. struct file_buffer *
  547. read_file (filename)
  548.      char *filename;
  549. {
  550.   int fd, size;
  551.   struct stat file_stats;
  552.   int namelen = strlen (filename);
  553.  
  554. #ifdef macintosh
  555.   fd = open (filename, O_RDONLY);
  556. #else
  557.   fd = open (filename, O_RDONLY, 0777);
  558. #endif
  559.   if (fd < 0)
  560.     sys_error (filename);
  561.  
  562.   if (fstat (fd, &file_stats) < 0)
  563.     sys_error (filename);
  564.  
  565.   if (fileptr.data != 0)
  566.     free (fileptr.data);
  567.   fileptr.size = file_stats.st_size;
  568.   fileptr.data = (char *) xmalloc (file_stats.st_size + 1);
  569.  
  570.   size = SYS_READ (fd, fileptr.data, fileptr.size);
  571.   if (size < 0)
  572.     sys_error (filename);
  573.   if (close (fd) < 0)
  574.     sys_error (filename);
  575.  
  576.   /* Apparently, the DOS stores files using CR-LF for newlines, but
  577.      then the DOS `read' changes them into '\n'.  Thus, the size of the
  578.      file on disc is larger than what is read into memory.  Thanks, Bill. */
  579.   if (size != fileptr.size)
  580.     fileptr.size = size;
  581.  
  582.   fileptr.name = (char *) xmalloc (namelen + 1);
  583.   memcpy (fileptr.name, filename, namelen);
  584.   fileptr.name[namelen] = '\0';
  585.  
  586.   fileptr.data[fileptr.size] = '\0';
  587.  
  588.   return &fileptr;
  589. }
  590.  
  591. /* This should come from stdio.h and be some system-optimal number */
  592. #ifndef BUFSIZ
  593. #define BUFSIZ 1024
  594. #endif
  595.  
  596. /* Suck the standard input into a file_buffer structure, and
  597.    return a pointer to that structure. */
  598.  
  599. struct file_buffer stdinptr;
  600.  
  601. struct file_buffer *
  602. read_stdin ()
  603. {
  604.   unsigned int size = 15 * BUFSIZ;
  605.   int ch;
  606.   register char *p;
  607.  
  608.   if (stdinptr.data != 0)
  609.     free (stdinptr.data);
  610.  
  611.   stdinptr.data = (char *) xmalloc (size + 1);
  612.   stdinptr.size = 0;
  613.   p = stdinptr.data;
  614.   do
  615.     {
  616.       while (stdinptr.size < size)
  617.     {
  618.       ch = getc (stdin);
  619.       if (ch == EOF)
  620.         break;
  621.  
  622.       *p++ = ch;
  623.       stdinptr.size++;
  624.     }
  625.  
  626.       if (ch != EOF)
  627.     {
  628.       size += (2 * BUFSIZ);
  629.       stdinptr.data = xrealloc (stdinptr.data, size);
  630.       p = stdinptr.data + stdinptr.size;
  631.     }
  632.     }
  633.   while (ch != EOF);
  634.  
  635.   stdinptr.name = "Standard Input";
  636.  
  637.   stdinptr.data[stdinptr.size] = '\0';
  638.  
  639.   return &stdinptr;
  640. }
  641.  
  642. /* Advance `buf_ptr' so that it points to the next line of input.
  643.  
  644.    If the next input line contains an indent control comment turning
  645.    off formatting (a comment, C or C++, beginning with *INDENT-OFF*),
  646.    then simply print out input lines without formatting until we find
  647.    a corresponding comment containing *INDENT-0N* which re-enables
  648.    formatting.
  649.  
  650.    Note that if this is a C comment we do not look for the closing
  651.    delimiter.  Note also that older version of this program also
  652.    skipped lines containing *INDENT** which represented errors
  653.    generated by indent in some previous formatting.  This version does
  654.    not recognize such lines. */
  655.  
  656. INLINE void
  657. fill_buffer ()
  658. {
  659.   register char *p;
  660.   int inhibit_formatting = 0;
  661.  
  662.   /* indent() may be saving the text between "if (...)" and the following
  663.      statement.  To do so, it uses another buffer (`save_com').  Switch
  664.      back to the previous buffer here. */
  665.   if (bp_save != 0)
  666.     {
  667.       buf_ptr = bp_save;
  668.       buf_end = be_save;
  669.       bp_save = be_save = 0;
  670.  
  671.       /* only return if there is really something in this buffer */
  672.       if (buf_ptr < buf_end)
  673.     return;
  674.     }
  675.  
  676.   /* If formatting gets turned off, then just loop here outputting lines
  677.      until formatting is re-enabled. */
  678.   do
  679.     {
  680.       /* Advance buf_ptr past last line, and return if EOF. */
  681.       cur_line = buf_ptr = in_prog_pos;
  682.       if (*buf_ptr == '\0')
  683.     {
  684.       had_eof = true;
  685.       return;
  686.     }
  687.  
  688.       /* Examine the beginning of the line for an indent control
  689.          comment. */
  690.       p = buf_ptr;
  691.       while (*p == ' ' || *p == TAB)
  692.     p++;
  693.       if (*p == '/' && (*(p + 1) == '*' || *(p + 1) == '/'))
  694.     {
  695.       p += 2;
  696.       while (*p == ' ' || *p == TAB)
  697.         p++;
  698.       if (! inhibit_formatting)
  699.         {
  700.           if (! strncmp (p, "*INDENT-OFF*", 12))
  701.         {
  702.           if (s_com != e_com || s_lab != e_lab || s_code != e_code)
  703.             dump_line ();
  704.           inhibit_formatting = 1;
  705.         }
  706.         }
  707.       else
  708.         {
  709.           if (! strncmp (p, "*INDENT-ON*", 11))
  710.         {
  711.           p += 11;
  712.           /* Set inhibit_formatting to 2 so that we will
  713.              still toss out this whole line, but drop out
  714.              of the loop afterwards. */
  715.           inhibit_formatting = 2;
  716.           n_real_blanklines = 0;
  717.           postfix_blankline_requested = 0;
  718.           prefix_blankline_requested = 0;
  719.           suppress_blanklines = 1;
  720.         }
  721.         }
  722.     }
  723.  
  724.       /* Now procede through the rest of the line */
  725.       while (*p != '\0' && *p != EOL)
  726.     p++;
  727.       buf_end = in_prog_pos = p + 1;
  728.  
  729.       if (inhibit_formatting)
  730.     {
  731.       p = buf_ptr;
  732.       while (p < buf_end)
  733.         putc (*p++, output);
  734.       if (inhibit_formatting == 2)
  735.         {
  736.           inhibit_formatting = 0;
  737.           continue;
  738.         }
  739.     }
  740.     }
  741.   while (inhibit_formatting);
  742. }
  743.  
  744. /* Fill the output line with whitespace up to TARGET_COLUMN, given that
  745.    the line is currently in column CURRENT_COLUMN.  Returns the ending
  746.    column. */
  747.  
  748. INLINE int
  749. pad_output (current_column, target_column)
  750.   register int current_column;
  751.   register int target_column;
  752. {
  753.   if (troff)
  754.     {
  755.       fprintf (output, "\\h'|%dp'", (int) ((target_column - 1) * 7));
  756.       return 0;
  757.     }
  758.  
  759.   if (current_column >= target_column)
  760.     return current_column;
  761.  
  762.   if (tabsize > 1)
  763.     {
  764.       register int offset;
  765.  
  766.       offset = tabsize - (current_column - 1) % tabsize;
  767.       while (current_column + offset <= target_column)
  768.     {
  769.       putc (TAB, output);
  770.       current_column += offset;
  771.       offset = tabsize;
  772.     }
  773.     }
  774.  
  775.   while (current_column < target_column)
  776.     {
  777.       putc (' ', output);
  778.       current_column++;
  779.     }
  780.  
  781.   return current_column;
  782. }
  783.  
  784. /* Nonzero if we have found an error (not a warning).  */
  785. int found_err;
  786.  
  787. /* Signal an error.  LEVEL is nonzero if it is an error (as opposed to a
  788.    warning.  MSG is a printf-style format string.  Additional arguments are
  789.    additional arguments for printf.  */
  790. /* VARARGS2 */
  791. diag (level, msg, a, b)
  792.      int level;
  793.      unsigned int a, b;
  794.      char *msg;
  795. {
  796.   if (level)
  797.     found_err = 1;
  798.  
  799. #ifdef MPW
  800.   fprintf (stderr, "File '%s'; Line %d\t# Indent - %s: ", in_name, line_no,
  801. #else
  802.   fprintf (stderr, "indent:%s:%d: %s: ", in_name, (int) line_no,
  803. #endif
  804.        level == 0 ? "Warning" : "Error");
  805.  
  806.   if (msg)
  807.     fprintf (stderr, msg, a, b);
  808.  
  809.   fprintf (stderr, "\n");
  810. #ifdef MPW
  811.   fflush (stderr);
  812. #endif
  813. }
  814.  
  815. writefdef (f, nm)
  816.      register struct fstate *f;
  817.      unsigned int nm;
  818. {
  819.   fprintf (output, ".ds f%c %s\n.nr s%c %d\n",
  820.        (int) nm, f->font, nm, (int) f->size);
  821. }
  822.  
  823. /* Write characters starting at S to change the font from OF to NF.  Return a
  824.    pointer to the character after the last character written. For troff mode
  825.    only.  */
  826. char *
  827. chfont (of, nf, s)
  828.      register struct fstate *of, *nf;
  829.      char *s;
  830. {
  831.   if (of->font[0] != nf->font[0]
  832.       || of->font[1] != nf->font[1])
  833.     {
  834.       *s++ = '\\';
  835.       *s++ = 'f';
  836.       if (nf->font[1])
  837.     {
  838.       *s++ = '(';
  839.       *s++ = nf->font[0];
  840.       *s++ = nf->font[1];
  841.     }
  842.       else
  843.     *s++ = nf->font[0];
  844.     }
  845.   if (nf->size != of->size)
  846.     {
  847.       *s++ = '\\';
  848.       *s++ = 's';
  849.       if (nf->size < of->size)
  850.     {
  851.       *s++ = '-';
  852.       *s++ = '0' + of->size - nf->size;
  853.     }
  854.       else
  855.     {
  856.       *s++ = '+';
  857.       *s++ = '0' + nf->size - of->size;
  858.     }
  859.     }
  860.   return s;
  861. }
  862.  
  863. void
  864. parsefont (f, s0)
  865.      register struct fstate *f;
  866.      char *s0;
  867. {
  868.   register char *s = s0;
  869.   int sizedelta = 0;
  870.   int i;
  871.  
  872.   f->size = 0;
  873.   f->allcaps = 1;
  874.   for (i = 0; i < 4; i++)
  875.     f->font[i] = 0;
  876.  
  877.   while (*s)
  878.     {
  879.       if (isdigit (*s))
  880.     f->size = f->size * 10 + *s - '0';
  881.       else if (isupper (*s))
  882.     if (f->font[0])
  883.       f->font[1] = *s;
  884.     else
  885.       f->font[0] = *s;
  886.       else if (*s == 'c')
  887.     f->allcaps = 1;
  888.       else if (*s == '+')
  889.     sizedelta++;
  890.       else if (*s == '-')
  891.     sizedelta--;
  892.       else
  893.     {
  894.       fprintf (stderr, "indent: bad font specification: %s\n", s0);
  895.       exit (1);
  896.     }
  897.       s++;
  898.     }
  899.   if (f->font[0] == 0)
  900.     f->font[0] = 'R';
  901.   if (bodyf.size == 0)
  902.     bodyf.size = 11;
  903.   if (f->size == 0)
  904.     f->size = bodyf.size + sizedelta;
  905.   else if (sizedelta > 0)
  906.     f->size += bodyf.size;
  907.   else
  908.     f->size = bodyf.size - f->size;
  909. }
  910.  
  911. #ifdef DEBUG
  912. void
  913. dump_debug_line ()
  914. {
  915.   fprintf (output, "\n*** Debug output marker line ***\n");
  916. }
  917.  
  918. #endif
  919.